package com.example.zxx.springboot3.util;


import cn.hutool.core.lang.Pair;

import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * IPairIfUtil:PairIf工具类
 *
 * @author zhangxiaoxiang
 * @date 2022年2月4日
 */
public interface IPairIfUtil {

    IPairIfUtil build = new IPairIfUtil() {
    };

    default <P> void pairsIfVoidByKey(P param, Pair<Boolean, Consumer<P>>... then) {
        pairsIfVoidByKey(param, null, then);
    }

    default <P> void pairsIfVoidByKey(P param, Consumer<P> defaultThen, Pair<Boolean, Consumer<P>>... then) {
        boolean thenExecute = false;
        for (Pair<Boolean, Consumer<P>> pair : then) {
            if (pair.getKey()) {
                thenExecute = true;
                pair.getValue().accept(param);
            }
        }
        if (!thenExecute && Objects.nonNull(defaultThen)) {
            defaultThen.accept(param);
        }
    }

    default <P, R> R pairsIfFunByKey(P param, Pair<Boolean, Function<P, R>>... then) {
        return pairsIfFunDefaultValByKey(param, null, then);
    }

    default <P, R> R pairsIfFunDefaultValByKey(P param, R defaultVal, Pair<Boolean, Function<P, R>>... then) {
        for (Pair<Boolean, Function<P, R>> pair : then) {
            if (pair.getKey()) {
                return pair.getValue().apply(param);
            }
        }
        return defaultVal;
    }

    default <P, R> R pairsIfFunDefaultFunByKey(P param, Function<P, R> defaultThen, Pair<Boolean, Function<P, R>>... then) {
        for (Pair<Boolean, Function<P, R>> pair : then) {
            if (pair.getKey()) {
                return pair.getValue().apply(param);
            }
        }
        return defaultThen.apply(param);
    }


    default <P> void pairsIfVoidByFields(P param, Pair<Predicate<P>, Consumer<P>>... then) {
        pairsIfVoidByFields(param, null, then);
    }

    default <P> void pairsIfVoidByFields(P param, Consumer<P> defaultThen, Pair<Predicate<P>, Consumer<P>>... then) {
        boolean thenExecute = false;
        for (Pair<Predicate<P>, Consumer<P>> pair : then) {
            if (pair.getKey().test(param)) {
                thenExecute = true;
                pair.getValue().accept(param);
            }
        }
        if (!thenExecute && Objects.nonNull(defaultThen)) {
            defaultThen.accept(param);
        }
    }

    default <P, R> R pairsIfFunByFields(P param, Pair<Predicate<P>, Function<P, R>>... then) {
        return pairsIfFunDefaultValByFields(param, null, then);
    }

    default <P, R> R pairsIfFunDefaultValByFields(P param, R defaultVal, Pair<Predicate<P>, Function<P, R>>... then) {
        for (Pair<Predicate<P>, Function<P, R>> pair : then) {
            if (pair.getKey().test(param)) {
                return pair.getValue().apply(param);
            }
        }
        return defaultVal;
    }

    default <P, R> R pairsIfFunDefaultFunByFields(P param, Function<P, R> defaultThen, Pair<Predicate<P>, Function<P, R>>... then) {
        for (Pair<Predicate<P>, Function<P, R>> pair : then) {
            if (pair.getKey().test(param)) {
                return pair.getValue().apply(param);
            }
        }
        return defaultThen.apply(param);
    }

    default <R> R pairsIfGetByTest(Pair<Supplier<Boolean>, Supplier<R>>... then) {
        return pairsIfGetDefaultValByTest(null, then);
    }

    default <R> R pairsIfGetDefaultValByTest(R defaultVal, Pair<Supplier<Boolean>, Supplier<R>>... then) {
        for (Pair<Supplier<Boolean>, Supplier<R>> pair : then) {
            if (pair.getKey().get()) {
                return pair.getValue().get();
            }
        }
        return defaultVal;
    }

    default <R> R pairsIfGetDefaultGetByTest(Supplier<R> elseThen, Supplier<R> defaultGet, Pair<Supplier<Boolean>, Supplier<R>>... then) {
        for (Pair<Supplier<Boolean>, Supplier<R>> pair : then) {
            if (pair.getKey().get()) {
                return pair.getValue().get();
            }
        }
        return defaultGet.get();
    }

}